﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using CodeKicker.BBCode;

namespace AutoLoL.Logic.Parsers
{
    public class BBCodeParser
    {
        private static readonly List<BBTag> tags = new List<BBTag>()
        {
            new BBTag("h1", "<TextBlock FontSize=\"19\" FontWeight=\"Bold\">", "</TextBlock><LineBreak/>"),
            new BBTag("h2", "<TextBlock FontSize=\"17\" FontWeight=\"Bold\">", "</TextBlock><LineBreak/>"),
            new BBTag("h3", "<TextBlock FontSize=\"15\" FontWeight=\"Bold\">", "</TextBlock><LineBreak/>"),
            new BBTag("h4", "<TextBlock FontSize=\"13\" FontWeight=\"Bold\">", "</TextBlock><LineBreak/>"),
            new BBTag("h5", "<TextBlock FontSize=\"11\" FontWeight=\"Bold\">", "</TextBlock><LineBreak/>"),
            new BBTag("b", "<Bold>", "</Bold>"),
            new BBTag("i", "<Italic>", "</Italic>"),
            new BBTag("u", "<Underline>", "</Underline>"),
            new BBTag("url", "<Hyperlink ToolTip=\"${href}\" NavigateUri=\"${href}\">", "</Hyperlink>", new BBAttribute("href", "", GetHrefAttribute)),
            new BBTag("color", "<TextBlock Foreground=\"${color}\">", "</TextBlock>", new BBAttribute("color", "", GetValidColorAttribute)),
            new BBTag("size", "<TextBlock FontSize=\"${size}\">", "</TextBlock>", new BBAttribute("size", "", GetValidFontSizeAttribute)),
            new BBTag("img", "<Image Source=\"${content}\" Width=\"${width}\" Height=\"${height}\" />", "", false, false, new BBAttribute("width", "width", GetValidImageSizeAttribute), new BBAttribute("height", "height", GetValidImageSizeAttribute)),
            new BBTag("br", "<LineBreak/>", "", true, false),
            new BBTag("hr", "<LineBreak/><Line X2=\"1\" Stroke=\"Black\" StrokeThickness=\"1\" Stretch=\"Fill\" Height=\"1\"/><LineBreak/>", "", true, false),
            new BBTag("goto", "<Hyperlink CommandParameter=\"${href}\">", "</Hyperlink>", new BBAttribute("href", "", GetHrefAttribute)),
            new BBTag("anchor", "<Span Tag=\"${content}\">", "</Span>")
            // Lists kinda work, but lets keep it simple for now
            // new BBTag("list", "<TextBlock Margin=\"10 0 0 0\">", "</TextBlock><LineBreak/>"),
            // new BBTag("*", "<BulletDecorator><BulletDecorator.Bullet><Ellipse Width=\"5\" Height=\"5\" Fill=\"Black\"/></BulletDecorator.Bullet><TextBlock Margin=\"4 0 0 0\">", "</TextBlock></BulletDecorator><LineBreak/>", true, true), 
        };

        public static TextBlock Parse(string input)
        {
            CodeKicker.BBCode.BBCodeParser parser = new CodeKicker.BBCode.BBCodeParser(ErrorMode.ErrorFree, null, tags);

            string result;
            try
            {
                result = parser.ToHtml(input);
            }
            catch (Exception ex1)
            {
                TextBlock t = new TextBlock();
                t.Text = ex1.Message;
                return t;
            }

            try
            {
                result = "<TextBlock>" + result + "</TextBlock>";

                System.Windows.Markup.ParserContext pc = new ParserContext();
                pc.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                pc.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");

                using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(result)))
                {
                    XamlReader reader = new XamlReader();
                    return (TextBlock)XamlReader.Load(stream, pc);
                }
            }
            catch (Exception ex2)
            {
                TextBlock t = new TextBlock();
                t.Text = ex2.Message;
                return t;
            }
        }

        private static string GetHrefAttribute(IAttributeRenderingContext attributeRenderingContext)
        {
            if (!string.IsNullOrEmpty(attributeRenderingContext.AttributeValue))
            {
                return attributeRenderingContext.AttributeValue;
            }

            var content = attributeRenderingContext.GetAttributeValueByID(BBTag.ContentPlaceholderName);
            if (!string.IsNullOrEmpty(content))
            {
                return content;
            }

            return null;
        }

        private static string GetValidColorAttribute(IAttributeRenderingContext attributeRenderingContext)
        {
            string[] colors = new string[] { "black", "red", "orange", "yellow", "green", "blue", "indigo", "violet" };
            if (!string.IsNullOrEmpty(attributeRenderingContext.AttributeValue))
            {
                if (colors.Contains(attributeRenderingContext.AttributeValue.ToLower()))
                {
                    return attributeRenderingContext.AttributeValue.ToLower();
                }
            }

            return "black";
        }

        private static string GetValidFontSizeAttribute(IAttributeRenderingContext attributeRenderingContext)
        {
            int input = 3;
            if (!string.IsNullOrEmpty(attributeRenderingContext.AttributeValue))
            {
                int t = 0;
                if (int.TryParse(attributeRenderingContext.AttributeValue, out t))
                {
                    input = t;
                }
            }

            switch (input)
            {
                case 5: return "18";
                case 4: return "14";
                case 2: return "9";
                case 1: return "7";
                case 3:
                default: return "11";
            }
        }

        private static string GetValidImageSizeAttribute(IAttributeRenderingContext attributeRenderingContext)
        {
            int input = -1;
            if (!string.IsNullOrEmpty(attributeRenderingContext.AttributeValue))
            {
                int t = 0;
                if (int.TryParse(attributeRenderingContext.AttributeValue, out t))
                {
                    input = t;
                }
            }

            if (input >= 0)
                return input.ToString();

            return "Auto";
        }
    }
}